﻿using System.Data;

namespace Bean.Entity.Dto.PolicyPushDto;

/// <summary>
/// 易旅行私有政策推送类
/// </summary>
public class OtaEtravelPrivatePolicyPushDto
{
    /// <summary>
    /// 适用建造者模式
    /// 私有化构造函数
    /// </summary>
    private OtaEtravelPrivatePolicyPushDto()
    {
    }

    /// <summary>
    /// 政策ID
    /// 单条政策唯一标识，用于更新或删除
    /// </summary>
    public string ExternalPolicyId { get; private set; }

    /// <summary>
    /// 政策代码
    /// 建议格式为X-Y-Z,用-隔开便于后续按照X/Y/Z、X-Y、Y-Z模糊查询删除
    /// </summary>
    public string PolicyCode { get; private set; }


    /// <summary>
    /// 产品类型
    /// 2：优选 3：特惠 6：特殊低价 7:特惠-O24 11-特惠不限
    /// </summary>
    public string ProductType { get; private set; }

    /// <summary>
    /// 行程类型
    /// 0：不限 1：单程 2:往返 （目前仅支付单程）
    /// </summary>
    public string TravelType { get; private set; }

    /// <summary>
    /// 航司
    /// 航司二字代码, 只能一个航司。
    /// </summary>
    public string Airline { get; private set; }

    /// <summary>
    /// 出发地
    /// 机场三字码 如SHA,NYC,SEL ALL表示不限制，多个用”,”分隔.最多允许输入500个字符
    /// </summary>
    public string DepCities { get; private set; }

    /// <summary>
    /// 目的地
    /// 机场三字码 如SHA,NYC,SEL ALL表示不限制，多个用”,”分隔.最多允许输入500个字符
    /// </summary>
    public string ArrCities { get; private set; }

    /// <summary>
    /// 排除航线
    /// 为空表示不限制，格式CANSHA,CTU,PEK(*表示所有机场)，多个英文逗号”,“分隔,最多1000字符
    /// </summary>
    public string routeForbid { get; private set; }

    /// <summary>
    /// 适用舱位
    /// 舱位代码，多个用“,”隔开
    /// </summary>
    public string cabin { get; private set; }

    /// <summary>
    /// 适用航班类型
    /// 单选 （0:全部, 1:适用航班, 2:不适用航班）
    /// </summary>
    public string goFlightRestrictType { get; private set; }

    /// <summary>
    /// 适用航班信息
    /// 往返用“,”隔开，多个航班号用”,”隔开，空表示不限制
    /// </summary>
    public string goFlightRestrict { get; private set; }

    /// <summary>
    /// 旅行日期
    /// 2018-08-01>2019-06-01，允许录入多个用,隔开表示或的关系
    /// </summary>
    public string goDateRestrict { get; private set; }


    /// <summary>
    /// 旅行排除日期
    /// 2018-08-01>2019-06-01，允许录入多个用,隔开表示或的关系，可为空表示不限制
    /// </summary>
    public string goDateRestrictForbid { get; private set; }

    /// <summary>
    /// 销售日期
    /// 销售日期：格式如2018-08-01>2019-06-01,多个“,”分割
    /// </summary>
    public string saleDateRestrict { get; private set; }

    /// <summary>
    /// 适用旅行时间
    /// 00:00-23:59，多个“,”分割，最多两段，为空表示不限制
    /// </summary>
    public string? goTimeRestrict { get; private set; }

    /// <summary>
    /// 适用班期
    /// 1,2,3,4,5,6,7
    /// </summary>
    public string weekRestrict { get; private set; }

    /// <summary>
    /// 提前出票天数
    /// 空表示不限制
    /// </summary>
    public string? advanceSaleDay { get; private set; }

    /// <summary>
    /// 最晚出票天数
    /// 空表示不限制
    /// </summary>
    public string maxSaleDay { get; private set; }

    /// <summary>
    /// 出票时间
    /// 如09:00-20:00, 多个用/分割
    /// </summary>
    public string workTime { get; private set; }

    /// <summary>
    /// 乘客类型
    /// 1: 成人（目前仅支持） 2: 儿童
    /// </summary>

    public string passengerType { get; private set; }

    /// <summary>
    /// 是否共享
    /// 0 否 1是
    /// </summary>
    public string canShare { get; private set; }

    /// <summary>
    /// 是否共享出主承运
    /// 0 否 1是 是否共享为1是必填，只有填写，开票才允许出主承运
    /// </summary>
    public string canOperateAirline { get; private set; }

    /// <summary>
    /// 适用共享航司
    /// </summary>
    public string includeShareAirlines { get; private set; }

    /// <summary>
    /// 排除共享航司
    /// </summary>
    public string excludeShareAirlines { get; private set; }

    /// <summary>
    /// 票面来源
    /// 0 指定票面 1取平台-适用舱位 2 官网
    /// </summary>
    public string ticketSource { get; private set; }

    /// <summary>
    /// 适用舱位票面
    /// 正整数，票面来源为0时必填
    /// </summary>
    public string ticketPrice { get; private set; }

    /// <summary>
    /// 航司返点
    /// 默认0，小数后两位小数（折上折产品）
    /// </summary>
    public string airlineRetention { get; private set; }

    /// <summary>
    /// 直减金额
    /// 默认0，小数点后保留2位小数（直减或券产品）
    /// </summary>
    public string directDecrease { get; private set; }

    /// <summary>
    /// 适用NFD取值
    /// 默认0,0-取高 1-取低(票面来源取系统时必填)，2-只取FD价格
    /// </summary>
    public string nfdCharge { get; private set; }

    /// <summary>
    /// 0-不验价 1-验价
    /// (当票面来源选择1- 取平台-适用舱位必填)
    /// </summary>
    public string isNeedPrice { get; private set; }

    /// <summary>
    /// 验价office号
    /// 是否验价=是，验价office必填
    /// </summary>
    public string testPriceOffice { get; private set; }

    /// <summary>
    /// 上浮价格
    /// </summary>
    public string upPrice { get; private set; }

    /// <summary>
    /// 返点
    /// 大于-0.4，两位小数,无需输入“%” ,eg: “10.01”表示“10.01%”
    /// </summary>
    public string saleRetention { get; private set; }


    /// <summary>
    /// 留钱
    /// </summary>
    public string saleRebase { get; private set; }

    /// <summary>
    /// 票面最低价格
    /// </summary>
    public string minPrice { get; private set; }

    /// <summary>
    /// 票面最高价格
    /// </summary>
    public string maxPrice { get; private set; }

    /// <summary>
    /// 是否换编
    /// </summary>
    public string isNeedBook { get; private set; }


    /// <summary>
    /// 是否代订座
    /// </summary>
    public string isReserveSeat { get; private set; }


    /// <summary>
    /// 余座阈值
    /// 是否代订座为2时，必填2-9数字，表示余坐低于多少时进行占座
    /// </summary>
    public string seatCount { get; private set; }

    /// <summary>
    /// 开票方式
    /// 1：BSP 2：B2B 3：官网 4：其它
    /// </summary>
    public string ticketType { get; private set; }

    /// <summary>
    /// 占座office号
    /// 是否代订座：“都订座”或者“按余座”占编office号必填
    /// </summary>
    public string bookingOffice { get; private set; }

    /// <summary>
    /// 开票office号
    /// 航信配置号，如SZV122
    /// </summary>
    public string ticketOffice { get; private set; }

    /// <summary>
    /// 授权office号
    /// 
    /// </summary>
    public string authorizeOfficeCode { get; private set; }

    /// <summary>
    /// 是否自动出票
    /// 0 否 1是
    /// </summary>
    public string autoTicketing { get; private set; }

    /// <summary>
    /// 适用年龄
    /// 年龄限制，如16-75，表示可售16-75岁，多段“,”分割，为空为不限制
    /// </summary>
    public string ageRestrict { get; private set; }

    /// <summary>
    /// 适用证件类型
    /// 枚举值：0 : “不限”,1 : “身份证””2 : “签证””3 : “护照””4 : “军官证””5 : “回乡证””6 : “港澳通行证””7 : “台胞证””8 : “台湾通行证””9 : “海员证””10 : “户口簿””11 : “外国人永久居留证””12 : “港澳居住证””13 : “台湾居民居住证”” 多个,逗号分隔
    /// </summary>
    public string credentialType { get; private set; }

    /// <summary>
    /// 身份证开头限制
    /// 适用证件类型如果包含身份证，则 这里必填
    /// </summary>
    public string idcardPrefix { get; private set; }

    /// <summary>
    /// 是否小团
    /// 单选 （0:否, 1:是）
    /// </summary>
    public string canGroupTickets { get; private set; }

    /// <summary>
    /// 最小出行人数
    /// 1-9，默认1
    /// </summary>
    public string minPeopleNum { get; private set; }

    /// <summary>
    /// 最大出行人数
    /// 1-9，默认1
    /// </summary>
    public string maxPeopleNum { get; private set; }

    /// <summary>
    /// 报销凭证
    /// 0：行程单 1：发票 3：行程单+差额发票 4：无
    /// </summary>
    public string reimbursementVoucher { get; private set; }

    /// <summary>
    /// 退改规则来源
    /// 0取系统，1自定义
    /// </summary>
    public string refundChangeRuleSource { get; private set; }


    /// <summary>
    /// 退票规则
    /// 退改规则来源为自定义时必填 格式：40-168-80-0-100，表示起飞前168小时之前的手续费比例是40%，起飞前168小时之内的手续费比例是80%，起飞后的手续费比例是100%
    /// </summary>
    public string refundFeeAllUnused { get; private set; }

    /// <summary>
    /// 改签规则
    /// 退改规则来源为自定义时必填 格式：40-168-80-0-100，表示起飞前168小时之前的手续费比例是40%，起飞前168小时之内的手续费比例是80%，起飞后的手续费比例是100%
    /// </summary>
    public string changeFeeGo { get; private set; }

    /// <summary>
    /// 政策备注
    /// </summary>
    public string memo { get; private set; }

    /// <summary>
    /// 特殊开票指令
    /// </summary>
    public string specialInvoiceInstruct { get; private set; }

    /// <summary>
    /// 运价基础码
    /// </summary>
    public string fareBasisRestrict { get; private set; }


    /// <summary>
    /// Builder
    /// </summary>
    public class Builder
    {
        private readonly OtaEtravelPrivatePolicyPushDto _dto = new OtaEtravelPrivatePolicyPushDto();

        /// <summary>
        /// 设置政策ID
        /// </summary>
        /// <param name="externalPolicyId">政策ID</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">政策ID不能为空</exception>
        public Builder SetExternalPolicyId(string externalPolicyId)
        {
            if (string.IsNullOrWhiteSpace(externalPolicyId))
            {
                throw new ArgumentException("政策ID不能为空", nameof(externalPolicyId));
            }

            _dto.ExternalPolicyId = externalPolicyId;
            return this;
        }

        /// <summary>
        /// 设置政策代码
        /// </summary>
        /// <param name="policyCode">政策代码</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">政策代码不能为空</exception>
        public Builder SetPolicyCode(string policyCode)
        {
            if (string.IsNullOrWhiteSpace(policyCode))
            {
                throw new ArgumentException("政策代码不能为空", nameof(policyCode));
            }

            _dto.PolicyCode = policyCode;
            return this;
        }

        /// <summary>
        /// 设置产品类型
        /// 2：优选 3：特惠 6：特殊低价 7:特惠-O24 11-特惠不限
        /// </summary>
        /// <param name="productType">产品类型</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">产品类型不能为空且必须是有效的值</exception>
        public Builder SetProductType(string productType)
        {
            if (string.IsNullOrWhiteSpace(productType))
            {
                throw new ArgumentException("产品类型不能为空", nameof(productType));
            }

            // 验证产品类型是否为有效值
            var validProductTypes = new[] { "2", "3", "6", "7", "11" };
            if (!validProductTypes.Contains(productType))
            {
                throw new ArgumentException("产品类型必须是有效的值: 2, 3, 6, 7, 11", nameof(productType));
            }

            _dto.ProductType = productType;
            return this;
        }

        /// <summary>
        /// 设置行程类型
        /// 0：不限 1：单程 2:往返 （目前仅支付单程）
        /// </summary>
        /// <param name="travelType">行程类型</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">行程类型不能为空且必须是有效的值</exception>
        public Builder SetTravelType(string travelType)
        {
            if (string.IsNullOrWhiteSpace(travelType))
            {
                throw new ArgumentException("行程类型不能为空", nameof(travelType));
            }

            // 验证行程类型是否为有效值
            var validTravelTypes = new[] { "0", "1", "2" };
            if (!validTravelTypes.Contains(travelType))
            {
                throw new ArgumentException("行程类型必须是有效的值: 0, 1, 2", nameof(travelType));
            }

            _dto.TravelType = travelType;
            return this;
        }

        /// <summary>
        /// 设置航司
        /// 航司二字代码, 只能一个航司。
        /// </summary>
        /// <param name="airline">航司</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">航司不能为空</exception>
        public Builder SetAirline(string airline)
        {
            if (string.IsNullOrWhiteSpace(airline))
            {
                throw new ArgumentException("航司不能为空", nameof(airline));
            }

            _dto.Airline = airline;
            return this;
        }

        /// <summary>
        /// 设置出发地
        /// 机场三字码 如SHA,NYC,SEL ALL表示不限制，多个用”,”分隔.最多允许输入500个字符
        /// </summary>
        /// <param name="depCities">出发地</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">出发地不能为空且长度不能超过500个字符</exception>
        public Builder SetDepCities(string depCities)
        {
            if (string.IsNullOrWhiteSpace(depCities))
            {
                depCities = "ALL";
            }

            _dto.DepCities = depCities;
            return this;
        }

        /// <summary>
        /// 设置目的地
        /// 机场三字码 如SHA,NYC,SEL ALL表示不限制，多个用”,”分隔.最多允许输入500个字符
        /// </summary>
        /// <param name="arrCities">目的地</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">目的地不能为空且长度不能超过500个字符</exception>
        public Builder SetArrCities(string arrCities)
        {
            if (string.IsNullOrWhiteSpace(arrCities))
            {
                arrCities = "ALL";
            }

            if (arrCities.Length > 500)
            {
                throw new ArgumentException("目的地长度不能超过500个字符", nameof(arrCities));
            }

            _dto.ArrCities = arrCities;
            return this;
        }

        /// <summary>
        /// 排除航线 航线黑名单
        /// </summary>
        /// <param name="routeForbid"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public Builder SetRouteForbid(string routeForbid)
        {
            _dto.routeForbid = routeForbid;
            return this;
        }

        /// <summary>
        /// 设置舱位
        /// 默认值：Y
        /// </summary>
        /// <param name="cabin"></param>
        /// <returns></returns>
        public Builder SetCabin(string cabin)
        {
            if (string.IsNullOrWhiteSpace(cabin))
            {
                throw new ArgumentException("适用舱位不能为空", nameof(cabin));
            }

            _dto.cabin = cabin;
            return this;
        }

        /// <summary>
        /// 适用航班类型
        /// 单选 （0:全部, 1:适用航班, 2:不适用航班）
        /// </summary>
        /// <param name="goFlightRestrictType"></param>
        /// <returns></returns>
        public Builder SetGoFlightRestrictType(string goFlightRestrictType = "0")
        {
            if (string.IsNullOrWhiteSpace(goFlightRestrictType))
            {
                throw new ArgumentException("适用航班类型不能为空", nameof(goFlightRestrictType));
            }

            _dto.goFlightRestrictType = goFlightRestrictType;
            return this;
        }

        /// <summary>
        /// 适用航班信息
        /// </summary>
        /// <param name="goFlightRestrict">往返用“,”隔开，多个航班号用”,”隔开，空表示不限制</param>
        /// <returns></returns>
        public Builder SetGoFlightRestrict(string goFlightRestrict = "")
        {
            _dto.goFlightRestrict = goFlightRestrict;
            return this;
        }

        /// <summary>
        /// 设置旅行日期
        /// 2018-08-01>2019-06-01，允许录入多个用,隔开表示或的关系
        /// </summary>
        /// <returns></returns>
        public Builder SetGoDateRestrict(string tripStartDate, string tripEndDate)
        {
            if (string.IsNullOrWhiteSpace(tripStartDate) || string.IsNullOrWhiteSpace(tripEndDate))
            {
                throw new ArgumentException("旅行日期不能为空", nameof(tripStartDate));
            }

            var goDateRestrict = $"{tripStartDate}>{tripEndDate}";
            _dto.goDateRestrict = goDateRestrict;
            return this;
        }

        /// <summary>
        /// 旅行排除日期
        /// 2018-08-01>2019-06-01，允许录入多个用,隔开表示或的关系，可为空表示不限制
        /// </summary>
        /// <returns></returns>
        public Builder SetgoDateRestrictForbid(string tripExceptStartDate = "", string tripExceptEndDate = "")
        {
            string goDateRestrictForbid = string.Empty;
            if (string.IsNullOrWhiteSpace(tripExceptStartDate) && string.IsNullOrWhiteSpace(tripExceptEndDate))
            {
                goDateRestrictForbid = $"{tripExceptStartDate}>{tripExceptEndDate}";
            }

            _dto.goDateRestrictForbid = goDateRestrictForbid;
            return this;
        }

        /// <summary>
        /// 销售日期
        /// </summary>
        /// <param name="saleStartDate"></param>
        /// <param name="saleEndDate"></param>
        /// <returns></returns>
        public Builder SetSaleDateRestrict(string saleStartDate, string saleEndDate)
        {
            if (string.IsNullOrWhiteSpace(saleStartDate) || string.IsNullOrWhiteSpace(saleEndDate))
            {
                throw new ArgumentException("销售日期不能为空");
            }

            var saleDateRestrict = $"{saleStartDate}>{saleEndDate}";
            _dto.saleDateRestrict = saleDateRestrict;
            return this;
        }

        /// <summary>
        /// 适用旅行时间
        /// </summary>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public Builder SetGoTimeRestrict(string tripStartTime, string tripEndTime)
        {
            string goTimeRestrict = String.Empty;
            if (!string.IsNullOrWhiteSpace(tripStartTime) && !string.IsNullOrWhiteSpace(tripEndTime))
            {
                goTimeRestrict = $"{tripStartTime}-{tripEndTime}";
            }

            _dto.goTimeRestrict = goTimeRestrict;
            return this;
        }

        /// <summary>
        /// 适用班期
        /// </summary>
        /// <param name="weekRestrict"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public Builder SetWeekRestrict(string weekRestrict = "1,2,3,4,5,6,7")
        {
            if (string.IsNullOrWhiteSpace(weekRestrict))
            {
                weekRestrict = "1,2,3,4,5,6,7";
            }

            _dto.weekRestrict = weekRestrict;
            return this;
        }

        /// <summary>
        /// 提前销售天数
        /// </summary>
        /// <param name="advanceSaleDay"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public Builder SetAdvanceSaleDay(string? advanceSaleDay)
        {
            _dto.advanceSaleDay = advanceSaleDay;
            return this;
        }

        /// <summary>
        /// 最晚出票天数
        /// </summary>
        /// <param name="maxSaleDay"></param>
        /// <returns></returns>
        public Builder SetMaxSaleDay(string maxSaleDay)
        {
            _dto.maxSaleDay = maxSaleDay;
            return this;
        }

        /// <summary>
        /// 出票时间
        /// </summary>
        /// <param name="workTime"></param>
        /// <returns></returns>
        public Builder SetWorkTime(string workTime)
        {
            _dto.workTime = workTime;
            return this;
        }

        /// <summary>
        /// 设置乘客类型
        /// 1: 成人（目前仅支持） 2: 儿童
        /// </summary>
        /// <param name="passengerType"></param>
        /// <returns></returns>
        public Builder SetPassengerType(string passengerType = "1")
        {
            _dto.passengerType = passengerType ?? "1";
            return this;
        }

        /// <summary>
        /// 是否共享
        /// 0: 不共享 1: 共享
        /// </summary>
        /// <param name="canShare"></param>
        /// <returns></returns>
        public Builder SetCanShare(string canShare = "0")
        {
            if (string.IsNullOrWhiteSpace(canShare))
            {
                canShare = "0";
            }

            _dto.canShare = canShare;
            return this;
        }

        /// <summary>
        /// 是否共享出主承运.
        /// 0 否 1是 是否共享为1是必填，只有填写，开票才允许出主承运
        /// </summary>
        /// <param name="canOperateAirline"></param>
        /// <returns></returns>
        public Builder SetCanOperateAirline(string canOperateAirline = "0")
        {
            if (_dto.canShare == "1" && string.IsNullOrWhiteSpace(canOperateAirline))
            {
                throw new InvalidOperationException("是否共享出主要承运 共享为1时必填");
            }

            _dto.canOperateAirline = canOperateAirline;
            return this;
        }

        /// <summary>
        /// 适用共享航司
        /// </summary>
        /// <param name="includeShareAirlines"></param>
        /// <returns></returns>
        public Builder SetIncludeShareAirlines(string includeShareAirlines = "")
        {
            _dto.includeShareAirlines = includeShareAirlines;
            return this;
        }

        /// <summary>
        /// 排除共享航司
        /// </summary>
        /// <param name="excludeShareAirlines"></param>
        /// <returns></returns>
        public Builder SetExcludeShareAirlines(string excludeShareAirlines = "")
        {
            _dto.excludeShareAirlines = excludeShareAirlines;
            return this;
        }

        /// <summary>
        /// 票面来源
        /// 0 指定票面 1取平台-适用舱位 2 官网
        /// </summary>
        /// <param name="ticketSource"></param>
        /// <returns></returns>
        public Builder SetTicketSource(string ticketSource)
        {
            if (string.IsNullOrWhiteSpace(ticketSource))
            {
                throw new InvalidOperationException("票面来源必填");
            }


            if (!new List<string>() { "0", "1", "2" }.Contains(ticketSource))
            {
                throw new InvalidOperationException("票面来源错误");
            }

            _dto.ticketSource = ticketSource;
            return this;
        }

        /// <summary>
        /// 适用舱位票面
        /// 正整数，票面来源为0时必填
        /// </summary>
        /// <param name="ticketPrice"></param>
        /// <returns></returns>
        public Builder SetTicketPrice(string ticketPrice)
        {
            if (_dto.ticketSource == "0" && string.IsNullOrWhiteSpace(ticketPrice))
            {
                throw new InvalidOperationException("票面来源时指定票面时 票面价格必填");
            }

            _dto.ticketPrice = ticketPrice;
            return this;
        }

        /// <summary>
        /// 航司返点
        /// </summary>
        /// <param name="airlineRetention"></param>
        /// <returns></returns>
        public Builder SetAirlineRetention(string airlineRetention = "0")
        {
            _dto.airlineRetention = airlineRetention;
            return this;
        }

        /// <summary>
        /// 直减金额
        /// 默认0，小数点后保留2位小数（直减或券产品）
        /// </summary>
        /// <param name="directDecrease"></param>
        /// <returns></returns>
        public Builder SetDirectDecrease(string directDecrease = "")
        {
            _dto.directDecrease = directDecrease;
            return this;
        }

        /// <summary>
        /// 适用NFD取值
        /// 默认0,0-取高 1-取低(票面来源取系统时必填)，2-只取FD价格
        /// </summary>
        public Builder SetNfdCharge(string nfdCharge = "")
        {
            _dto.nfdCharge = nfdCharge;
            return this;
        }

        ///  <summary>
        ///  是否验价
        ///  0-不验价 1-验价
        /// (当票面来源选择1- 取平台-适用舱位必填)
        ///  </summary>
        ///  <param name="isNeedPrice"></param>
        ///  <returns></returns>
        public Builder SetIsNeedPrice(string isNeedPrice = "")
        {
            if (_dto.ticketSource == "1" && string.IsNullOrWhiteSpace(isNeedPrice))
            {
                throw new InvalidOperationException("当票面来源选择1时 是否验价必填");
            }

            _dto.isNeedPrice = isNeedPrice;
            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="testPriceOffice"></param>
        /// <returns></returns>
        /// <exception cref="AggregateException"></exception>
        public Builder SetTestPriceOffice(string testPriceOffice = "")
        {
            if (_dto.isNeedPrice == "1" && string.IsNullOrWhiteSpace(_dto.isNeedPrice))
            {
                throw new AggregateException("需要验价时 验价Office号必填");
            }

            _dto.testPriceOffice = testPriceOffice;
            return this;
        }

        /// <summary>
        /// 上浮价
        /// </summary>
        /// <param name="upPrice"></param>
        /// <returns></returns>
        public Builder SetUpPrice(string upPrice)
        {
            _dto.upPrice = upPrice;
            return this;
        }

        /// <summary>
        /// 返点百分比
        /// 大于-0.4，两位小数,无需输入“%” ,eg: “10.01”表示“10.01%”
        /// </summary>
        /// <param name="saleRetention"></param>
        /// <returns></returns>
        public Builder SetSaleRetention(string saleRetention)
        {
            _dto.saleRetention = saleRetention;
            return this;
        }

        /// <summary>
        /// 留钱
        /// </summary>
        /// <param name="saleRebase"></param>
        /// <returns></returns>
        public Builder SetSaleRebase(string saleRebase = "")
        {
            _dto.saleRebase = saleRebase;

            return this;
        }

        /// <summary>
        /// 票面最低价
        /// </summary>
        /// <param name="minPrice"></param>
        /// <returns></returns>
        public Builder SetMinPrice(string minPrice)
        {
            _dto.minPrice = minPrice;
            return this;
        }

        /// <summary>
        /// 票面最高价
        /// </summary>
        /// <param name="maxPrice"></param>
        /// <returns></returns>
        public Builder SetMaxPrice(string maxPrice)
        {
            _dto.maxPrice = maxPrice;

            return this;
        }

        /// <summary>
        /// 是否换编
        /// </summary>
        /// <param name="isNeedBook"></param>
        /// <returns></returns>
        public Builder SetIsNeedBook(string isNeedBook = "1")
        {
            _dto.isNeedBook = isNeedBook;

            return this;
        }

        /// <summary>
        /// 是否待订座
        /// </summary>
        /// <param name="isReserveSeat"></param>
        /// <returns></returns>
        public Builder SetIsReserveSeat(string isReserveSeat = "0")
        {
            if (string.IsNullOrWhiteSpace(isReserveSeat))
            {
                isReserveSeat = "0";
            }

            _dto.isReserveSeat = isReserveSeat;
            return this;
        }

        /// <summary>
        /// 余坐阈值
        /// 是否代订座为2时，必填2-9数字，表示余坐低于多少时进行占座
        /// </summary>
        /// <param name="seatCount"></param>
        /// <returns></returns>
        public Builder SetSeatCount(string seatCount)
        {
            if (_dto.isReserveSeat == "2" && string.IsNullOrWhiteSpace(seatCount))
            {
                throw new InvalidOperationException("代订座为2时 余座阈值必填");
            }

            _dto.seatCount = seatCount;

            return this;
        }

        /// <summary>
        /// 开票方式
        /// 1：BSP 2：B2B 3：官网 4：其它
        /// </summary>
        /// <param name="ticketType"></param>
        /// <returns></returns>
        public Builder SetTicketType(string ticketType)
        {
            if (string.IsNullOrWhiteSpace(ticketType))
            {
                throw new InvalidConstraintException("开票方式不能为空");
            }

            _dto.ticketType = ticketType;
            return this;
        }

        /// <summary>
        /// 占座office号
        /// 是否代订座：“都订座”或者“按余座”，占编office号必填（只允许录入供应商自身的office号，不允许录入平台的office号）
        /// </summary>
        /// <param name="bookingOffice"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public Builder SetBookingOffice(string bookingOffice)
        {
            if ((_dto.isReserveSeat is "1" or "2") && string.IsNullOrWhiteSpace(bookingOffice))
            {
                throw new InvalidOperationException("“都订座”或者“按余座” 占编office号");
            }

            _dto.bookingOffice = bookingOffice;
            return this;
        }

        /// <summary>
        /// 开票office号
        /// </summary>
        public Builder SetTicketOffice(string ticketOffice)
        {
            _dto.ticketOffice = ticketOffice;
            return this;
        }

        /// <summary>
        /// 授权office号
        /// </summary>
        /// <param name="authorizeOfficeCode"></param>
        /// <returns></returns>
        public Builder SetAuthorizeOfficeCode(string authorizeOfficeCode)
        {
            _dto.authorizeOfficeCode = authorizeOfficeCode;
            return this;
        }

        /// <summary>
        /// 是否自动出票
        /// 0 否 1是
        /// </summary>
        /// <param name="autoTicketing"></param>
        /// <returns></returns>
        public Builder SetAutoTicketing(string autoTicketing = "0")
        {
            _dto.autoTicketing = autoTicketing;
            return this;
        }

        /// <summary>
        /// 适用年龄
        /// 年龄限制，如16-75，表示可售16-75岁，多段“,”分割，为空为不限制
        /// </summary>
        /// <param name="ageRestrict"></param>
        /// <returns></returns>
        public Builder SetAgeRestrict(string ageRestrict = "")
        {
            _dto.ageRestrict = ageRestrict;
            return this;
        }

        /// <summary>
        /// 适用证件类型
        /// 枚举值：0 : “不限”,1 : “身份证””2 : “签证””3 : “护照””4 : “军官证””5 : “回乡证””6 : “港澳通行证””7 : “台胞证””8 : “台湾通行证””9 : “海员证””10 : “户口簿””11 : “外国人永久居留证””12 : “港澳居住证””13 : “台湾居民居住证”” 多个,逗号分隔
        /// </summary>
        /// <param name="credentialType"></param>
        /// <returns></returns>
        public Builder SetCredentialType(string credentialType = "0")
        {
            _dto.credentialType = credentialType;
            return this;
        }

        /// <summary>
        /// 身份证开头限制
        /// 适用证件类型如果包含身份证，则 这里必填
        /// </summary>
        /// <returns></returns>
        public Builder SetIdcardPrefix(string idcardPrefix = "")
        {
            if (_dto.credentialType.Contains("1") && string.IsNullOrWhiteSpace(idcardPrefix))
            {
                throw new InvalidCastException("适用证件类型包含身份证时必填");
            }

            _dto.idcardPrefix = idcardPrefix;
            return this;
        }

        /// <summary>
        /// 是否小团
        /// 单选 （0:否, 1:是）
        /// </summary>
        /// <param name="canGroupTickets"></param>
        /// <returns></returns>
        public Builder SetCanGroupTickets(string canGroupTickets = "0")
        {
            _dto.canGroupTickets = canGroupTickets;
            return this;
        }

        /// <summary>
        /// 最小出行人数
        /// </summary>
        /// <param name="minPeopleNum"></param>
        /// <returns></returns>
        public Builder SetMinPeopleNum(string minPeopleNum = "1")
        {
            _dto.minPeopleNum = minPeopleNum;
            return this;
        }

        /// <summary>
        /// 最大出行人数
        /// </summary>
        /// <param name="maxPeopleNum"></param>
        /// <returns></returns>
        public Builder SetMaxPeopleNum(string maxPeopleNum = "1")
        {
            _dto.maxPeopleNum = maxPeopleNum;
            return this;
        }

        /// <summary>
        /// 报销凭证
        /// 0：行程单 1：发票 3：行程单+差额发票 4：无
        /// </summary>
        /// <returns></returns>
        public Builder SetReimbursementVoucher(string reimbursementVoucher = "4")
        {
            _dto.reimbursementVoucher = reimbursementVoucher;
            return this;
        }

        /// <summary>
        /// 退改规则来源
        /// 0取系统，1自定义
        /// </summary>
        /// <param name="refundChangeRuleSource"></param>
        /// <returns></returns>
        public Builder SetRefundChangeRuleSource(string refundChangeRuleSource = "0")
        {
            _dto.refundChangeRuleSource = refundChangeRuleSource;
            return this;
        }

        /// <summary>
        /// 退票规则
        /// 退改规则来源为自定义时必填 格式：40-168-80-0-100，表示起飞前168小时之前的手续费比例是40%，起飞前168小时之内的手续费比例是80%，起飞后的手续费比例是100%
        /// </summary>
        /// <returns></returns>
        public Builder SetRefundChangeRule(string refundFeeAllUnused)
        {
            _dto.refundFeeAllUnused = refundFeeAllUnused;
            return this;
        }

        /// <summary>
        /// 改签规则
        /// 退改规则来源为自定义时必填 格式：40-168-80-0-100，表示起飞前168小时之前的手续费比例是40%，起飞前168小时之内的手续费比例是80%，起飞后的手续费比例是100%
        /// </summary>
        /// <returns></returns>
        public Builder SetChangeFeeGo(string changeFeeGo)
        {
            _dto.changeFeeGo = changeFeeGo;
            return this;
        }

        /// <summary>
        /// 政策备注
        /// </summary>
        /// <param name="memo"></param>
        /// <returns></returns>
        public Builder SetMemo(string memo)
        {
            _dto.memo = memo;
            return this;
        }

        /// <summary>
        /// 特殊开票指令
        /// </summary>
        /// <param name="specialInvoiceInstruct"></param>
        /// <returns></returns>
        public Builder SetSpecialInvoiceInstruct(string specialInvoiceInstruct)
        {
            _dto.specialInvoiceInstruct = specialInvoiceInstruct;
            return this;
        }

        /// <summary>
        /// 运价基础码
        /// 获取退改规则可能会依赖
        /// </summary>
        /// <returns></returns>
        public Builder SetfareBasisRestrict(string? fareBasisRestrict)
        {
            _dto.fareBasisRestrict = fareBasisRestrict ?? "";
            return this;
        }


        /// <summary>
        /// 构建 OtaEtravelPrivatePolicyPushDto 对象
        /// </summary>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException">必要的字段未设置</exception>
        public OtaEtravelPrivatePolicyPushDto Build()
        {
            if (string.IsNullOrWhiteSpace(_dto.ExternalPolicyId))
            {
                throw new InvalidOperationException("政策ID不能为空");
            }

            if (string.IsNullOrWhiteSpace(_dto.PolicyCode))
            {
                throw new InvalidOperationException("政策代码不能为空");
            }

            if (string.IsNullOrWhiteSpace(_dto.ProductType))
            {
                throw new InvalidOperationException("产品类型不能为空");
            }

            if (string.IsNullOrWhiteSpace(_dto.TravelType))
            {
                throw new InvalidOperationException("行程类型不能为空");
            }

            if (string.IsNullOrWhiteSpace(_dto.Airline))
            {
                throw new InvalidOperationException("航司不能为空");
            }

            if (string.IsNullOrWhiteSpace(_dto.DepCities))
            {
                throw new InvalidOperationException("出发地不能为空");
            }

            if (string.IsNullOrWhiteSpace(_dto.ArrCities))
            {
                throw new InvalidOperationException("目的地不能为空");
            }

            return _dto;
        }
    }
}